package cn.zyl.common.redis.constant;

import cn.zyl.common.redis.command.MiniRedisForConnection;
import cn.zyl.common.redis.command.MiniRedisForServer;
import cn.zyl.common.redis.util.MiniRedisInputStream;
import cn.zyl.common.redis.util.MiniRedisOutputStream;
import cn.zyl.common.redis.util.MiniRedisTool;
import cn.zyl.common.redis.util.MiniSafeEncoderTool;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.exceptions.*;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * RedisProtocol类说明: redis连接相关常量
 *
 * @author wsz
 * @version v1.0
 * @date 2020-08-07
 */
public final class MiniRedisProtocol {
    /** 默认ip地址*/
    public static final String DEFAULT_HOST = "localhost";
    /** 默认redis节点端口*/
    public static final int DEFAULT_PORT = 6379;
    /** 默认redis哨兵端口*/
    public static final int DEFAULT_SENTINEL_PORT = 26379;
    /** 默认超时时间*/
    public static final int DEFAULT_TIMEOUT = 2000;
    /** 默认redis数据库索引*/
    public static final int DEFAULT_DATABASE = 0;
    /** 默认编码*/
    public static final String CHARSET = "UTF-8";

    /** redis-哨兵-控制节点-字符串*/
    public static final String SENTINEL_MASTERS = "masters";
    public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name";
    public static final String SENTINEL_RESET = "reset";
    /** redis-哨兵-子节点-字符串*/
    public static final String SENTINEL_SLAVES = "slaves";
    /** redis-哨兵-故障转移*/
    public static final String SENTINEL_FAILOVER = "failover";
    /** redis-哨兵-班长*/
    public static final String SENTINEL_MONITOR = "monitor";
    /** redis-哨兵-移除*/
    public static final String SENTINEL_REMOVE = "remove";
    /** redis-哨兵-设置*/
    public static final String SENTINEL_SET = "set";
    /** redis-集群-节点*/
    public static final String CLUSTER_NODES = "nodes";
    /** redis-集群-集合*/
    public static final String CLUSTER_MEET = "meet";
    /** redis-集群-重置*/
    public static final String CLUSTER_RESET = "reset";
    /** redis-集群-添加槽点*/
    public static final String CLUSTER_ADDSLOTS = "addslots";
    /** redis-集群-删除槽点*/
    public static final String CLUSTER_DELSLOTS = "delslots";
    /** redis-集群-信息*/
    public static final String CLUSTER_INFO = "info";
    public static final String CLUSTER_GETKEYSINSLOT = "getkeysinslot";
    public static final String CLUSTER_SETSLOT = "setslot";
    public static final String CLUSTER_SETSLOT_NODE = "node";
    public static final String CLUSTER_SETSLOT_MIGRATING = "migrating";
    public static final String CLUSTER_SETSLOT_IMPORTING = "importing";
    public static final String CLUSTER_SETSLOT_STABLE = "stable";
    public static final String CLUSTER_FORGET = "forget";
    public static final String CLUSTER_FLUSHSLOT = "flushslots";
    public static final String CLUSTER_KEYSLOT = "keyslot";
    public static final String CLUSTER_COUNTKEYINSLOT = "countkeysinslot";
    public static final String CLUSTER_SAVECONFIG = "saveconfig";
    public static final String CLUSTER_REPLICATE = "replicate";
    public static final String CLUSTER_SLAVES = "slaves";
    public static final String CLUSTER_FAILOVER = "failover";
    public static final String CLUSTER_SLOTS = "slots";
    public static final String PUBSUB_CHANNELS = "channels";
    public static final String PUBSUB_NUMSUB = "numsub";
    public static final String PUBSUB_NUM_PAT = "numpat";

    public static final byte[] BYTES_TRUE = toByteArray(1);
    public static final byte[] BYTES_FALSE = toByteArray(0);
    public static final byte[] BYTES_TILDE = MiniSafeEncoderTool.encode("~");

    public static final byte[] POSITIVE_INFINITY_BYTES = "+inf".getBytes();
    public static final byte[] NEGATIVE_INFINITY_BYTES = "-inf".getBytes();

    public static byte[] toByteArray(final boolean value) {
        return value ? BYTES_TRUE : BYTES_FALSE;
    }
    public static byte[] toByteArray(final int val) {
        return MiniSafeEncoderTool.encode(String.valueOf(val));
    }

    public static void main(String[] args) {
        //参数列表
        byte[][] arg =  new byte[0][];
        //命令
        byte[] command = MiniRedisForConnection.PING.getRaw();
        //阻塞io模式
        bIoTest(command,arg);
    }
    private static void bIoTest(byte[] command,byte[][] arg){
        try (Socket socket = new Socket()){
            //启用/禁用套接字选项
            socket.setReuseAddress(true);
            //将监视TCP连接是否有效
            socket.setKeepAlive(true);
            //套接字缓冲区是否关闭，以确保及时传递数据 miniRedis
            socket.setTcpNoDelay(true);
            //启用/禁用SO_LINGER与以秒为单位指定的逗留时间
            socket.setSoLinger(true, 0);
            //将此套接字连接到具有指定超时值的服务器
            socket.connect(new InetSocketAddress(DEFAULT_HOST,DEFAULT_PORT), DEFAULT_TIMEOUT);
            socket.setSoTimeout(DEFAULT_TIMEOUT);
            MiniRedisOutputStream os = new MiniRedisOutputStream(socket.getOutputStream());
            MiniRedisInputStream is = new MiniRedisInputStream(socket.getInputStream());
            //发送命令
            os.write(MiniRedisTool.RES_LIST);
            os.writeIntCrLf(arg.length + 1);
            os.write(MiniRedisTool.RES_BYTE);
            os.writeIntCrLf(command.length);
            os.write(command);
            os.writeCrLf();
            //刷新流
            os.flush();
            //获取响应流,解析命令
            byte[] resp = (byte[]) MiniRedisTool.process(is);
            System.out.println("bIoTest>>> byte[] resp---:"+Arrays.toString(resp));
            System.out.println("bIoTest>>> result:"+MiniSafeEncoderTool.encode(resp));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
